/**
 *
 * keywords.c --
 *    lexical token lookup for reserved words in postgres SQL
 *
 ******************************************************************************
 */

#include "c.h"
#include "nodes/op_list.h"
#include "nodes/parse_nodes.h"
#include "parser/keywords.h"
#include "parser/gram.tab.h"
/*
 * List of (keyword-name, keyword-token-value) pairs.
 *
 * !!WARNING!!: This list must be sorted, because binary
 *	 search is used to locate entries.
 */
scan_keywords_t scan_keywords[] = {
	/* name			value		*/
	{ "all",		ALL		},
	{ "alter",		ALTER		},
	{ "and",		AND		},
	{ "as",                 AS              },
	{ "asc",		ASC             },
	{ "by",			BY		},
	{ "column",		COLUMN		},
	{ "create",		CREATE		},
	{ "database",		DATABASE	},
	{ "delete",		DELETE		},
	{ "desc",		DESC		},
	{ "distinct",		DISTINCT	},
	{ "execute",		EXECUTE		},
	{ "explain",		EXPLAIN		},
	{ "from",		FROM		},

	{ "grant",              GRANT           },
	{ "group",		GROUP		},
	{ "having",		HAVING		},
	{ "in",			IN		},
	{ "index",		INDEX		},
	{ "insert",		INSERT		},
	{ "into",		INTO		},
	{ "isnull",             ISNULL          },
	{ "like",		LIKE		},
	{ "not",		NOT		},
	{ "notnull",            NOTNULL         },
	{ "null",		PNULL		},
	{ "on",			ON		},
	{ "or",			OR		},
	{ "order",		ORDER		},
	{ "recipe",             RECIPE          },
	{ "select",		SELECT		},
	{ "set",		SET		},
	{ "table",		TABLE		},
	{ "to",			TO		},
	{ "update",		UPDATE		},
	{ "using",		USING		},
	{ "values",		VALUES		},
	{ "view",		VIEW		},
	{ "where",		WHERE		},
	{ "with",		WITH		}
};

scan_keywords_t *scan_keywords_lookup(char *text)
{
	scan_keywords_t	*low  = &scan_keywords[0];
	scan_keywords_t	*high = endof(scan_keywords) - 1;
	scan_keywords_t	*middle;
	int		difference;

	while (low <= high) {
		middle = low + (high - low) / 2;
		/* keywords case-insensitive (for SQL) -- ay 8/94 */
		difference = strcasecmp(middle->name, text);
		if (difference == 0)
			return (middle);
		else if (difference < 0)
			low = middle + 1;
		else
			high = middle - 1;
	}

	return (NULL);
}

#if 0
static table_map tableMap[] = {
	/* W3 */
	{"W3_ID", 1},
	{"W3_PN", 2},
	{"W3_ED", 3},
	{"W3_CT", 4},
	{"W3_TM", 5},
	{"W3_AS", 6},
	{"W3_AV", 7},
	{"W3_AU", 8},   /* all unit */
	{"W3_AP", 9}    /* all point */

	/* UNIT */
	{"UNIT_ID", 11},
	{"UNIT_ND", 12},
	{"UNIT_RT", 13},
	{"UNIT_PN", 14},
	{"UNIT_ED", 15},
	{"UNIT_FQ", 16},
	{"UNIT_KZ", 17},
	{"UNIT_AR", 18},
	{"UNIT_CT", 19},
	{"UNIT_TM", 20},
	{"UNIT_AS", 21},
	{"UNIT_AV", 22},
	{"UNIT_AP", 23},    /* all point */

	/* POINT */
	{"ID", 101},
	{"ND", 102},
	{"PT", 103},
	{"RT", 104},
	{"PN", 105},
	{"AN", 106},
	{"ED", 107},
	{"KR", 108},
	{"FQ", 109},
	{"CP", 110},
	{"HW", 111},
	{"BP", 112},
	{"LC", 113},
	{"AP", 114},
	{"AR", 115},
	{"FL", 116},
	{"CT", 117},
	{"ST", 118},
	{"RS", 119},
	{"EU", 120},
	{"FM", 121},
	{"IV", 122},
	{"BV", 123},
	{"TV", 124},
	{"LL", 125},
	{"HL", 126},
	{"ZL", 127},
	{"ZH", 128},
	{"DB", 129},
	{"DT", 130},
	{"KZ", 131},
	{"TT", 132},
	{"TP", 133},
	{"TO", 134},
	{"KT", 135},
	{"EX", 136},
	{"TM", 137},
	{"AS", 138},
	{"AV", 139},
	{"TR", 140}
};
#endif

/*
 * 一下的as字段跟SQL的AS关键字冲突,
 * 暂时不处理带有AS的SQL语句,待以后改进
 */
table_map_t tableMap[] = {
	/* POINT */
	{"AN", 106},
	{"AP", 114},
	{"AR", 115},
	{"AS", 138},
	{"AV", 139},
	{"BP", 112},
	{"BV", 123},
	{"CT", 117},
	{"CP", 110},
	{"DB", 129},
	{"DT", 130},
	{"EU", 120},
	{"ED", 107},
	{"EX", 136},
	{"FL", 116},
	{"FM", 121},
	{"FQ", 109},
	{"KR", 108},
	{"KT", 135},
	{"KZ", 131},
	{"HL", 126},
	{"HW", 111},
	{"ID", 101},
	{"IV", 122},
	{"LC", 113},
	{"LL", 125},
	{"ND", 102},
	{"PT", 103},
	{"PN", 105},
	{"RS", 119},
	{"RT", 104},
	{"ST", 118},
	{"TM", 137},
	{"TO", 134},
	{"TP", 133},
	{"TR", 140},
	{"TT", 132},
	{"TV", 124},
	{"ZH", 128},   /* 0~38 */

	/* UNIT */
	{"AP", 23},    /* all point */
	{"AR", 18},
	{"AS", 21},
	{"AV", 22},
	{"CT", 19},
	{"ED", 15},
	{"FQ", 16},
	{"ID", 11},
	{"KZ", 17},
	{"ND", 12},
	{"PN", 14},
	{"RT", 13},
	{"TM", 20},     /* 39~51  */

	/* W3 */
	{"AP", 9},      /* all point */
	{"AS", 6},
	{"AU", 8},      /* all unit */
	{"AV", 7},
	{"CT", 4},
	{"ED", 3},
	{"ID", 1},
	{"PN", 2},
	{"TM", 5}       /* 52~60 */
};

/**
 * scan_table_map
 *  查找tableMap[],根据dim来确定查找的范围
 *
 * @param: text[in] 被查找字段
 *         dim[int] 确定查找的范围
 * @return: middle/NULL
 * @note:
 */
table_map_t* scan_table_map(const char *text, const int dim)
{
	table_map_t *low = NULL;
	table_map_t *high = NULL;
	table_map_t *middle = NULL;
	int difference = 0;

	/*
	 * 只处理单个数据库时的表结构
	 * DB维度,dim == 1
	 * NODE维度, dim == 2
	 * POINT维度, dim == 3
	 *
	 * 对于tableMap的索引,在添加字段
	 * 时要作调整,这点设计不当.
	 */
	switch (dim) {
		case 1:
			low = &tableMap[52];
			high = &tableMap[60];
			break;
		case 2:
			low = &tableMap[39];
			high = &tableMap[51];
			break;
		case 3:
			low = &tableMap[0];
			high = &tableMap[38];
			break;
		default:
			break;
	}

	while (low <= high)
	{
		middle = low + (high - low) / 2;
		difference = strcasecmp(middle->field_name, text);
		if (difference == 0)
		{
			return middle;
		}
		else if (difference < 0)
		{
			low = middle + 1;
		}
		else
		{
			high= middle - 1;
		}
	}

	return NULL;
}
